# ------------------------------------------------------------------------------------
# Helper to use RobWork from outside project
#
# set ROBWORK_DIR to installation path to find root of sdurw, else automatic finding will be used
# based on RobWork_DIR
#
# ROBWORK_LIBRARIES is filled with all available RobWork libraries ROBWORK_INCLUDE_DIRS is filled
# with RobWork and available 3rdparty headers ROBWORK_LIBRARY_DIRS is filled with RobWork components
# libraries install directory and 3rdparty libraries paths
#
# www.robwork.dk
# ------------------------------------------------------------------------------------

# ---[ Find RobWork

if(ROBWORK_FIND_QUIETLY)
    set(QUIET_ QUIET)
else(ROBWORK_FIND_QUIETLY)
    set(QUIET_)
endif(ROBWORK_FIND_QUIETLY)

# ############################################# MACROS #####################

# macro for determining the best RobWork build type match
macro(GET_ROBWORK_BUILD_TYPE CFG_ROOT RW_BUILD_TYPE)
    # defaults to release
    set(BTYPE_TMP release)
    if(CMAKE_BUILD_TYPE)
        string(TOLOWER ${CMAKE_BUILD_TYPE} BTYPE_TMP)
    else()
        set(BTYPE_TMP "none")
    endif()

    # first test if the correct cmake build type is installed
    if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_${BTYPE_TMP}.cmake)
        set(${RW_BUILD_TYPE} ${BTYPE_TMP})
    else()

        # find best robwork build match
        if(${BTYPE_TMP} STREQUAL "release")
            # find release compatible robwork installation
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "minsizerel")
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "relwithdebinfo")
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "debug")
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_none.cmake)
                set(${RW_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        elseif(${BTYPE_TMP} STREQUAL "none")
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        else()
            message(
                STATUS
                    "Does not recognize build type: ${CMAKE_BUILD_TYPE} choosing any existing RobWork installation!"
            )
            if(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_release.cmake)
                set(${RW_BUILD_TYPE} release)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_minsizerel.cmake)
                set(${RW_BUILD_TYPE} minsizerel)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_relwithdebinfo.cmake)
                set(${RW_BUILD_TYPE} relwithdebinfo)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_debug.cmake)
                set(${RW_BUILD_TYPE} debug)
            elseif(EXISTS ${CFG_ROOT}/RobWorkBuildConfig_none.cmake)
                set(${RWS_BUILD_TYPE} none)
            else()
                message(FATAL_ERROR "Could not find any build of RobWork!")
            endif()
        endif()

        message(
            STATUS
                "warning: RobWork was not compiled with type:${BTYPE_TMP} using type:${${RW_BUILD_TYPE}} instead!"
        )
    endif()

endmacro()

macro(RW_MESSAGE text)
    if(IS_INSTALL)
        message(STATUS ${text})
    endif()
endmacro()

# ##################################################################################################

get_filename_component(RWCFG_ROOT ${CMAKE_CURRENT_LIST_FILE} PATH)

# check if user specified a RobWork_DIR
if(DEFINED ROBWORK_DIR)
    if(EXISTS "${ROBWORK_DIR}/src/RobWorkConfig.hpp")
        # Found RobWork in a build tree of RobWork
        set(RWCFG_ROOT "${ROBWORK_DIR}/cmake")
    elseif(EXISTS "${ROBWORK_DIR}/RobWorkConfig.cmake")
        # Found a RobWork installation
        set(RWCFG_ROOT "${ROBWORK_DIR}")
    elseif(
        EXISTS
        "${ROBWORK_DIR}/include/robwork-${RobWork_VERSION_MAJOR}.${RobWork_VERSION_MINOR}/RobWorkConfig.hpp"
    )
        set(RWCFG_ROOT
            "${ROBWORK_DIR}/share/robwork-${RobWork_VERSION_MAJOR}.${RobWork_VERSION_MINOR}/"
        )
    else()
        # found no RobWork installation ot build tree in RobWork_DIR so we try extracting it from
        # RobWorkConfig.cmake location instead
    endif()
endif()

# get the relavant build type
get_robwork_build_type(${RWCFG_ROOT} RW_BUILD_TYPE)

if(NOT TARGET sdurw)
    include("${RWCFG_ROOT}/RobWorkTargets.cmake")
endif()

# check whether RobWorkConfig.cmake is found into a RobWork installation or in a build tree
if(EXISTS "${RWCFG_ROOT}/../src/RobWorkConfig.hpp")
    # Found RobWorkConfig.cmake in a build tree of RobWork
    set(succmsg "RobWork: Found a RobWork build tree")
    set(RW_ROOT "${RWCFG_ROOT}/..")

    set(RW_INCLUDE_EXT "${RW_ROOT}/ext")
    set(RW_INCLUDE_SRC "${RW_ROOT}/src")
    set(RW_LIBS "${RW_ROOT}/libs/${RW_BUILD_TYPE}")
    set(IS_INSTALL FALSE)
else()
    set(succmsg "RobWork: Found a RobWork installation")
    set(IS_INSTALL TRUE)
    # Found a RobWork installation
    if(WIN32)
        # RobWorkConfig.cmake is installed to RW_ROOT/cmake
        set(RW_ROOT "${RWCFG_ROOT}/../..")
        set(RW_INCLUDE_EXT "${RWCFG_ROOT}/../ext")
        set(RW_INCLUDE_SRC
            "${RW_ROOT}/include/robwork-${RobWork_VERSION_MAJOR}.${RobWork_VERSION_MINOR}"
        )
        set(RW_LIBS "${RW_ROOT}/lib")
    else()
        # RobWorkConfig.cmake is installed to RW_INTALL/share/robwork-x.y/cmake

        set(RW_ROOT "${RWCFG_ROOT}")
        set(RW_INSTALL "${RWCFG_ROOT}/../../..")
        set(RW_LIBS "${RW_INSTALL}/lib")
        set(RW_INCLUDE_SRC
            "${RW_INSTALL}/include/robwork-${RobWork_VERSION_MAJOR}.${RobWork_VERSION_MINOR}"
        )
        set(RW_INCLUDE_EXT
            "${RW_INSTALL}/include/robwork-${RobWork_VERSION_MAJOR}.${RobWork_VERSION_MINOR}/ext"
        )
    endif()
endif()

# ##################################################################################################
# now RW_ROOT and RWCFG_ROOT is set. Lets extract the stuff needed to run a project

# next get the build configuration of the requested built type
if(EXISTS ${RWCFG_ROOT}/RobWorkBuildConfig_${RW_BUILD_TYPE}.cmake)
    include(${RWCFG_ROOT}/RobWorkBuildConfig_${RW_BUILD_TYPE}.cmake)

    if(${RW_BUILD_WITH_FREEGLUT})
        find_package(FreeGLUT REQUIRED)
    endif()

    set(BOOST_ROOT ${RW_BUILD_WITH_BOOST_ROOT})
    set(BOOST_INCLUDEDIR ${RW_BUILD_WITH_BOOST_INCLUDE_DIR})
    set(BOOST_LIBRARYDIR ${RW_BUILD_WITH_BOOST_LIBRARY_DIR})

    if(DEFINED WIN32 AND ${IS_INSTALL})
        set(BOOST_INCLUDEDIR "${RW_INCLUDE_EXT}/boost")
        set(BOOST_LIBRARYDIR "${RW_LIBS}")
    endif()

    # check which components to include
    set(LIBRARIES_TO_INCLUDE) # Libraries that must be included
    set(OPTIONAL_LIBRARIES_TO_INCLUDE) # libraries that are included if they have been build

    if(RobWork_FIND_COMPONENTS)
        # FIRST check if all required components are installed/build
        set(LIBRARIES_TO_INCLUDE sdurw)
        foreach(
            component
            IN
            LISTS RobWork_FIND_COMPONENTS
        )
            if(NOT (${component} STREQUAL "sdurw"))
                set(FILTER "sdurw_${component}")
                string(REGEX MATCH ${FILTER} RESULT "${RW_BUILD_WITH_LIBRARIES}")

                unset(FOUND CACHE)
                if(RESULT)
                    find_library(
                        FOUND ${RESULT}
                        PATHS ${RW_LIBS}
                        PATH_SUFFIXES ${RW_BUILD_WITH_LIBRARY_SUBDIRS}
                        NO_DEFAULT_PATH
                    )
                endif()

                if(FOUND)
                    list(APPEND LIBRARIES_TO_INCLUDE "sdurw_${component}")
                    set(RobWork_${component}_FOUND TRUE)
                else()
                    set(RobWork_${component}_FOUND FALSE)
                    if(RobWork_REQUIRED)
                        set(ROBWORK_EXPERIENCED_FATAL_PROBLEMS TRUE)
                        message(
                            FATAL_ERROR
                                "The component: sdurw_${component} has not been built with RobWork. Reconfigure RobWork installation or check component spelling!"
                        )
                    else()
                        set(ROBWORK_EXPERIENCED_FATAL_PROBLEMS TRUE)
                        message(
                            WARNING
                                "The component: sdurw_${component} has not been built with RobWork. Reconfigure RobWork installation or check component spelling!"
                        )
                    endif()
                endif()
            endif()
        endforeach()
    else()
        foreach(lib IN LISTS RW_BUILD_WITH_LIBRARIES)
            unset(FOUND CACHE)
            find_library(
                FOUND ${lib}
                PATHS ${RW_LIBS}
                PATH_SUFFIXES ${RW_BUILD_WITH_LIBRARY_SUBDIRS} NO_DEFAULT_PATH
            )
            if(FOUND)
                list(APPEND OPTIONAL_LIBRARIES_TO_INCLUDE "${lib}")
                rw_message("Looking for ${lib} - found")
            else()
                if(${lib} STREQUAL "sdurw")
                    list(APPEND OPTIONAL_LIBRARIES_TO_INCLUDE "${lib}")
                    rw_message("Looking for ${lib} - not found")
                else()
                    rw_message("Looking for ${lib} - not found (ignored)")
                endif()

            endif()
        endforeach()
    endif()

    # Set extra compiler flags. The user should be able to change this
    set(RW_C_FLAGS
        ${RW_BUILD_WITH_C_FLAGS}
        CACHE STRING "Change this to force using your own
                      flags and not those of RobWork"
    )
    set(RW_CXX_FLAGS
        ${RW_BUILD_WITH_CXX_FLAGS}
        CACHE STRING "Change this to force using your own
                      flags and not those of RobWork"
    )
    set(RW_DEFINITIONS
        ${RW_BUILD_WITH_DEFINITIONS}
        CACHE STRING "Change this to force using your own
                      definitions and not those of RobWork"
    )
    add_definitions(${RW_DEFINITIONS})
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RW_CXX_FLAGS}")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RW_C_FLAGS}")

    # Set extra linker flags. The user should be able to change this
    set(RW_LINKER_FLAGS
        ${RW_BUILD_WITH_LINKER_FLAGS}
        CACHE STRING "Change this to force using your own linker
                      flags and not those of RobWork"
    )
    set(CMAKE_SHARED_LINKER_FLAGS
        "${CMAKE_SHARED_LINKER_FLAGS} ${RW_LINKER_FLAGS}"
        CACHE STRING "" FORCE
    )
    set(CMAKE_MODULE_LINKER_FLAGS
        "${CMAKE_MODULE_LINKER_FLAGS} ${RW_LINKER_FLAGS}"
        CACHE STRING "" FORCE
    )
    if(WIN32)
        set(CMAKE_EXE_LINKER_FLAGS
            "${CMAKE_EXE_LINKER_FLAGS} ${RW_LINKER_FLAGS}"
            CACHE STRING "" FORCE
        )
    endif()

    # ################ FIND ROBWORK #######################
    set(ROBWORK_BUILD_PATH "${RW_BUILD_WITH_RW_ROOT}")
    set(ROBWORK_LIBRARIES_TMP
        "${LIBRARIES_TO_INCLUDE};${OPTIONAL_LIBRARIES_TO_INCLUDE};${RW_BUILD_WITH_LIB_DEPEND}"
    )

    # make sure that the library and include paths are pointing to the right locations

    # ######### Include Directories #############
    string(REPLACE "${ROBWORK_BUILD_PATH}/ext" "${RW_INCLUDE_EXT}" ROBWORK_INCLUDE_DIRS
                   "${RW_BUILD_WITH_INCLUDE_DIR}"
    )
    string(REPLACE "${ROBWORK_BUILD_PATH}/src" "${RW_INCLUDE_SRC}" ROBWORK_INCLUDE_DIRS
                   "${ROBWORK_INCLUDE_DIRS}"
    )
    if(WIN32)
        list(APPEND ROBWORK_INCLUDE_DIRS "${RW_INCLUDE_EXT}")
    endif()

    list(REMOVE_DUPLICATES ROBWORK_INCLUDE_DIRS)

    # ######### Library Paths #############
    string(REPLACE "${ROBWORK_BUILD_PATH}/libs/${RW_BUILD_TYPE}" "${RW_LIBS}" ROBWORK_LIBRARY_DIRS
                   "${RW_BUILD_WITH_LIBRARY_DIRS}"
    )
    list(REMOVE_DUPLICATES ROBWORK_LIBRARY_DIRS)

    string(REPLACE "${ROBWORK_BUILD_PATH}/libs/${RW_BUILD_TYPE}" "${RW_LIBS}" ROBWORK_LIBRARIES
                   "${ROBWORK_LIBRARIES_TMP}"
    )
    if(${IS_INSTALL} AND DEFINED WIN32)
        string(REPLACE "${RW_BUILD_WITH_BOOST_LIBRARY_DIR}/" "" ROBWORK_LIBRARIES
                       "${ROBWORK_LIBRARIES}"
        )
    endif()
    list(REMOVE_DUPLICATES ROBWORK_LIBRARIES)

    # Find and add full path information for the RobWork libraries
    set(ROBWORK_LIBRARIES_TMP ${ROBWORK_LIBRARIES})
    set(ROBWORK_LIBRARIES)
    foreach(l ${ROBWORK_LIBRARIES_TMP})
        unset(tmp CACHE)
        find_library(
            tmp ${l}
            PATHS ${RW_LIBS}
            PATH_SUFFIXES ${RW_BUILD_WITH_LIBRARY_SUBDIRS} NO_DEFAULT_PATH
        )

        if(tmp)
            list(APPEND ROBWORK_LIBRARIES "${tmp}")
        else()
            list(APPEND ROBWORK_LIBRARIES "${l}")
        endif()
    endforeach()

    set(ROBWORK_INCLUDE_DIR "${ROBWORK_INCLUDE_DIRS}")

else()
    message(
        STATUS
            "This build of RobWork is not compiled in ${RW_BUILD_TYPE} please specify another buildtype!"
    )
endif()

if(RW_BUILD_WITH_GTEST AND NOT ${IS_INSTALL})
    if(NOT TARGET gtest AND RW_BUILD_WITH_INTERNAL_GTEST)
        find_package(Threads QUIET)
        include("${RWCFG_ROOT}/gtestTargets.cmake")
    endif()
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
    RobWork
    "Found RobWork-Version ${RobWork_VERSION}"
    RW_ROOT
    ROBWORK_LIBRARIES
    ROBWORK_INCLUDE_DIRS
    ROBWORK_INCLUDE_DIR
    ROBWORK_LIBRARY_DIRS
)
mark_as_advanced(ROBWORK_LIBRARIES ROBWORK_INCLUDE_DIRS ROBWORK_INCLUDE_DIR ROBWORK_LIBRARY_DIRS)

if(ROBWORK_FOUND)
    set(ROBWORK_VERSION
        ${RobWork_VERSION}
        CACHE STRING "RobWork version"
    )
endif(ROBWORK_FOUND)
